home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / GX Libraries / ScalerLibrary.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-07  |  12.4 KB  |  339 lines  |  [TEXT/MPS ]

  1.  
  2. /*
  3.     File:        ScalerLibrary.c
  4.  
  5.     Contains:    graphics libraries - routines used to call gxFont scalers directly
  6.     
  7.     Written by:    Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good, Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink, Chris Yerga
  8.     
  9.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.  
  13.          <2>      4/7/95    jtd        taking out all references to 'GestaltEqu.h'
  14.          <1>      1/9/95    JD        First checked in.
  15. */
  16.  
  17. #include <Memory.h>         /* NewPtr(), DisposePtr() */
  18. #include <Gestalt.h>
  19. #include <Components.h>            /* Component Manager declarations */
  20. #include <ScalerTypes.h>        /* Scaler API declarations and definitions */
  21. #include "ScalerLibrary.h"        /* The library's decls and defs. */
  22.  
  23. #define kComponentScalerType    'sclr'          /* Type-gxTag for gxFont scaler components */
  24. #ifndef __powerc
  25. #define PostScalerError(c,e) (((c)->PostErrorFunction != nil && (e) != scaler_no_problem)? (c)->PostErrorFunction((c),(e)),e: e)
  26. #else
  27. #define PostScalerError(c,e) (((c)->PostErrorFunction && (e) != scaler_no_problem) ? CallPostErrorFunctionProc((c)->PostErrorFunction,(c),(e)),(e):(e))
  28. #endif
  29.  
  30. typedef struct {
  31.     gxFontFormatTag       format;                 /* Font format the scaler supports */
  32.     Component       theScalerComponent;         /* Used to open the component scaler */
  33.     ComponentInstance   theOpenedScalerComponent;   /* Component scaler (if 0, needs opening)*/
  34. } scalerEntry, *scalerEntryPtr;                 /* Information associated with a component gxFont scaler */
  35.  
  36. typedef struct {
  37.     long                oldSeed;                    /* Component Mgr's instance seed */
  38.     long                numScalers;             /* Number of scalers in the list */
  39.     scalerEntry     entries[1];             /* The array of scalers */
  40. } scalerList, *scalerListPtr;                       /* Component gxFont scaler list structure */
  41.  
  42. static  scalerListPtr   theListOfScalers = nil;     /* The list (really an array) of all registered component scalers */
  43.  
  44. static  Boolean     FindComponentFontScalers(void);
  45. static  scalerError FindMatchingOpenScaler(ComponentInstance *theScaler, scalerContext *theContext);
  46. static  Boolean     FindComponentFontScalers(void);
  47. static  scalerListPtr   BuildScalerList(void);
  48. static  scalerEntryPtr  FindMatchingScaler(scalerListPtr theList, gxFontFormatTag format);
  49. static  scalerListPtr   UpdateScalerList(scalerListPtr oldList);
  50.  
  51. scalerError FontScalerOpen( scalerContext* context, scalerInfo* theInfo)
  52. {
  53.     scalerError error;
  54.     ComponentInstance   theOpenScaler;
  55.     
  56.     if (!context) return scaler_null_context;
  57.     
  58.     if (theListOfScalers == nil)
  59.         if (!FindComponentFontScalers())
  60.             return PostScalerError(context,scaler_unsupported_font_format);
  61.     
  62.     if ((error = FindMatchingOpenScaler(&theOpenScaler, context)) == 0) {
  63.         error = ComponentFontScalerOpen(theOpenScaler, context, theInfo);
  64.     }
  65.     
  66.     return error;
  67. }
  68.  
  69. scalerError FontScalerClose( scalerContext* context)
  70. {
  71.     scalerError error;
  72.     ComponentInstance   theOpenScaler;
  73.     
  74.     if (!context) return scaler_null_context;
  75.  
  76.     if ((error = FindMatchingOpenScaler(&theOpenScaler, context)) == 0) {
  77.         error = ComponentFontScalerClose(theOpenScaler, context);
  78.     }
  79.     
  80.     return error;
  81. }
  82.  
  83. scalerError FontScalerNewFont( scalerContext* context, scalerFontInfo* info)
  84. {
  85.     scalerError error;
  86.     ComponentInstance   theOpenScaler;
  87.     
  88.     if (!context) return scaler_null_context;
  89.  
  90.     if ((error = FindMatchingOpenScaler(&theOpenScaler, context)) == 0) {
  91.         error = ComponentFontScalerNewFont(theOpenScaler, context, info);
  92.     }
  93.     
  94.     return error;
  95. }
  96.  
  97. scalerError FontScalerNewVariation( scalerContext* context, long count, const gxFontVariation variation[])
  98. {
  99.     scalerError error;
  100.     ComponentInstance   theOpenScaler;
  101.     
  102.     if (!context) return scaler_null_context;
  103.  
  104.     if ((error = FindMatchingOpenScaler(&theOpenScaler, context)) == 0) {
  105.         error = ComponentFontScalerNewVariation(theOpenScaler, context, count, (gxFontVariation*)variation);
  106.     }
  107.     
  108.     return error;
  109. }
  110.  
  111. scalerError FontScalerNewTransform( scalerContext* context, const scalerTransform* trans, scalerTransformInfo* info)
  112. {
  113.     scalerError error;
  114.     ComponentInstance   theOpenScaler;
  115.     
  116.     if (!context) return scaler_null_context;
  117.  
  118.     if ((error = FindMatchingOpenScaler(&theOpenScaler, context)) == 0) {
  119.         error = ComponentFontScalerNewTransform(theOpenScaler, context, trans, info);
  120.     }
  121.     
  122.     return error;
  123. }
  124.  
  125. scalerError FontScalerNewGlyph( scalerContext* context, const scalerGlyph* glyph, scalerMetrics* theMetrics, scalerBitmap* bitImage, void* outlineData)
  126. {
  127.     scalerError error;
  128.     ComponentInstance   theOpenScaler;
  129.     
  130.     if (!context) return scaler_null_context;
  131.  
  132.     if ((error = FindMatchingOpenScaler(&theOpenScaler, context)) == 0) {
  133.         error = ComponentFontScalerNewGlyph(theOpenScaler, context, glyph, theMetrics, bitImage, outlineData);
  134.     }
  135.     
  136.     return error;
  137. }
  138.  
  139. scalerError FontScalerKernGlyphs( scalerContext* context, scalerKerning* kerning, gxPoint deltas[], scalerKerningNote flags[], gxPoint locations[])
  140. {
  141.     scalerError error;
  142.     ComponentInstance   theOpenScaler;
  143.     
  144.     if (!context) return scaler_null_context;
  145.  
  146.     if ((error = FindMatchingOpenScaler(&theOpenScaler, context)) == 0) {
  147.         error = ComponentScalerKernGlyphs(theOpenScaler, context,  kerning, deltas, flags, locations);
  148.     }
  149.     
  150.     return error;
  151. }
  152.  
  153. scalerError FontScalerStreamFont( scalerContext* context, scalerStream* stream)
  154. {
  155.     scalerError error;
  156.     ComponentInstance   theOpenScaler;
  157.     
  158.     if (!context) return scaler_null_context;
  159.  
  160.     if ((error = FindMatchingOpenScaler(&theOpenScaler, context)) == 0) {
  161.         error = ComponentFontScalerStreamFont(theOpenScaler, context, stream);
  162.     }
  163.     
  164.     return error;
  165. }
  166.  
  167. /*
  168. **  CloseAllOpenFontScalers()   -   Runs down the list of registered component scalers and closes the open ones.
  169. */
  170. void    CloseAllOpenFontScalers(void)
  171. {
  172.     if (theListOfScalers != nil) {
  173.         unsigned short  whichScaler;
  174.         
  175.         for (whichScaler = 0; whichScaler < theListOfScalers->numScalers; whichScaler++) {
  176.             if (theListOfScalers->entries[whichScaler].theOpenedScalerComponent != nil) {
  177.                 CloseComponent(theListOfScalers->entries[whichScaler].theOpenedScalerComponent);
  178.             }
  179.         }
  180.         
  181.         DisposePtr((Ptr)theListOfScalers);
  182.         theListOfScalers = nil;
  183.     }
  184. }
  185.  
  186. /*
  187. **  FindComponentFontScalers()  -   Called during the first ScalerOpen() call, this routine first determines whether the 
  188. **                          Component Manager is present.  If it is, it registers the built-in scalers and then
  189. **                          asks the Component Manager to find all of the registered scaler components.  A list
  190. **                          of these is built, and if all goes well the routine will return true, indicating that
  191. **                          component gxFont scalers are in use.  If it returns false, the built-in scalers will
  192. **                          need to be called directly.
  193. */
  194. static  Boolean FindComponentFontScalers()
  195. {
  196.     long    dummyLong;
  197.     
  198.     if (Gestalt(gestaltComponentMgr, &dummyLong) == 0) {
  199.         if ((theListOfScalers = BuildScalerList()) != 0) {
  200.             return true;
  201.         }
  202.     }
  203.  
  204.     return false;
  205. }
  206.  
  207. /*
  208. **  FindMatchingScaler()    -   Given a gxFont format and the list of all registered component gxFont scalers, it looks for
  209. **                      a scaler (actually the first) that supports the format and returns the address of
  210. **                      its list entry.  It will return nil if no scaler is found for the format.
  211. */
  212. static  scalerEntryPtr  FindMatchingScaler(register scalerListPtr theList, gxFontFormatTag format)
  213. {
  214.     unsigned short  numScalers;
  215.     register scalerEntryPtr entry;
  216.     
  217.     numScalers = theList->numScalers;
  218.     entry = theList->entries;
  219.     do {
  220.         if (entry->format == format)
  221.             return entry;
  222.         entry++;
  223.     } while (--numScalers);
  224.     
  225.     return nil;
  226. }
  227.  
  228. /*
  229. **  UpdateScalerList()  -   Builds a new list of registered scalers in response to a changed component list
  230. **                      seed.  It copies from the old list the entries for those scalers that are in both lists.
  231. */
  232. static  scalerListPtr   UpdateScalerList(scalerListPtr oldList)
  233. {
  234.     scalerListPtr       newList;
  235.     unsigned short      whichScaler;
  236.     scalerEntryPtr      oldEntry;
  237.     
  238.     newList = BuildScalerList();        /* Create an all-new scaler list */
  239.     
  240.     /* We copy the entries from the old list for those scalers in both lists (they may be open)*/
  241.     for (whichScaler = 0; whichScaler < newList->numScalers; whichScaler++) {
  242.         if ((oldEntry = FindMatchingScaler(oldList, newList->entries[whichScaler].format)) != 0) {
  243.             newList->entries[whichScaler] = *oldEntry;
  244.         }
  245.     }
  246.     
  247.     DisposePtr((Ptr)oldList);
  248.     theListOfScalers = newList;
  249.     
  250.     return newList;
  251. }
  252.  
  253. /*
  254. **  BuildScalerList()   -   Queries the Component Manager to find all currently registered component scalers.
  255. **                      It allocates and builds a list of these scalers.
  256. */
  257. static  scalerListPtr   BuildScalerList()
  258. {
  259.     long                    numScalers;
  260.     ComponentDescription    looking, theInfo;
  261.     register    scalerListPtr   newList = nil;
  262.     
  263.     /* Fill in the description structure */
  264.     looking.componentType           = kComponentScalerType;
  265.     looking.componentSubType            = kAnyComponentSubType;
  266.     looking.componentManufacturer       = kAnyComponentManufacturer;
  267.     looking.componentFlags          = 0;
  268.     looking.componentFlagsMask      = 0;
  269.     
  270.     /* Count the number of components and create our list based on that number*/
  271.     
  272.     numScalers = CountComponents(&looking);
  273.     
  274.     {   register scalerEntryPtr entry;
  275.         Component           lastComponent = 0, currentComponent;
  276.         
  277.         newList = (scalerListPtr) NewPtr(sizeof(scalerList) + (numScalers - 1)*sizeof(scalerEntry));
  278.         
  279.         newList->oldSeed        = GetComponentListModSeed();
  280.         newList->numScalers = numScalers;
  281.             
  282.         /* For each scaler, get its info and remember the subtype, this is the format */
  283.         entry = newList->entries;
  284.         do {
  285.             currentComponent = FindNextComponent(lastComponent, &looking);
  286.         
  287.             if (GetComponentInfo(currentComponent,&theInfo, nil, nil, nil) == 0) {
  288.                 entry->format                   = theInfo.componentSubType;
  289.                 entry->theScalerComponent       = currentComponent;
  290.                 entry->theOpenedScalerComponent = nil;
  291.             } else
  292.                 entry->format = 0;  /* unusable scaler */
  293.                 
  294.             lastComponent = currentComponent;
  295.             entry++;
  296.         } while(--numScalers);
  297.     }
  298.     
  299.     return newList;
  300. }
  301.  
  302. /*
  303. **  FindMatchingOpenScaler()    -   This routine will look for a component scaler that supports the gxFont format
  304. **                          specified in the given scalerContext.  If necessary, the list of scalers will be
  305. **                          updated.  If a matching component scaler is found and is not open, the component
  306. **                          is opened.
  307. **
  308. **                          The routine returns scaler_no_problem if all went well,
  309. **                          scaler_unsupported_font_format if a component was not found or couldn't be
  310. **                          opened.
  311. **
  312. **                          If scaler_no_problem is returned *theOpenScaler will contain the
  313. **                          component instance for the desired scaler, else it will be undefined.
  314. */
  315. static  scalerError FindMatchingOpenScaler(ComponentInstance* theOpenScaler, scalerContext* theContext)
  316. {
  317.     scalerError result = scaler_no_problem;
  318.     scalerEntryPtr  theScaler;
  319.     
  320.     /* Check if a component was added while we were away, we may need to update the list of scalers */
  321.     if (GetComponentListModSeed() != theListOfScalers->oldSeed)
  322.         theListOfScalers = UpdateScalerList(theListOfScalers);
  323.         
  324.     theScaler = FindMatchingScaler(theListOfScalers, theContext->format);
  325.     
  326.     if (theScaler == nil) { 
  327.         result = scaler_unsupported_font_format;
  328.     } else {
  329.         if (theScaler->theOpenedScalerComponent == nil) {
  330.             if ((theScaler->theOpenedScalerComponent = OpenComponent(theScaler->theScalerComponent)) == nil)
  331.                 result = scaler_unsupported_font_format;
  332.         }
  333.         
  334.         *theOpenScaler = theScaler->theOpenedScalerComponent;
  335.     }
  336.     
  337.     return PostScalerError(theContext, result);
  338. }
  339.